﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlueNinjaSoftware.HIDLib;
using BlueNinjaSoftware.HIDLib.Reports;

namespace StrategicCommanderCenter
{
    public enum StrategicLedStatus
    {
        Off,
        On,
        Blink
    }

    public class LEDManager : IDisposable
    {
        private readonly byte[] LedFirst = { 1, 4, 16, 64 };
        private readonly byte[] LedSecond = { 1, 4, 16 };

        private HIDDevice mssc;
        private HIDFeatureReport rep;
        private ReportDecoder dec;
        private StrategicConfig conf;

        private StrategicLedStatus[] LedStatus = new StrategicLedStatus[8] {
            StrategicLedStatus.On, 
            StrategicLedStatus.On, 
            StrategicLedStatus.On, 
            StrategicLedStatus.On, 
            StrategicLedStatus.On, 
            StrategicLedStatus.On, 
            StrategicLedStatus.On, 
            StrategicLedStatus.On };

        public LEDManager(HIDDevice device, ReportDecoder decoder, StrategicConfig config)
        {
            mssc = device;
            rep = device.CreateFeatureReport(1);
            dec = decoder;
            dec.Changed += ChangedState;
            conf = config;
            SetLedFromState(dec.CurrentState);
            RefreshLedStatus();
        }

        private void ChangedState(object sender, ChangedStateArgs e)
        {
            SetLedFromState(e.NewState);
        }

        private void SetLedFromState(StrategicState state)
        {
            StrategicShiftState sState = StrategicShiftState.None;
            if (state.ButtonStates[(int)StrategicButtons.Shift1])
                sState = StrategicShiftState.Shift1;
            else if (state.ButtonStates[(int)StrategicButtons.Shift2])
                sState = StrategicShiftState.Shift2;
            else if (state.ButtonStates[(int)StrategicButtons.Shift3])
                sState = StrategicShiftState.Shift3;

            SetLedFromConfig(sState, state.CurrentProfile);
        }

        private void SetLedFromConfig(StrategicShiftState shift, StrategicProfileSelector prof)
        {
            SetButton(StrategicButtons.Button1, shift, prof);
            SetButton(StrategicButtons.Button2, shift, prof);
            SetButton(StrategicButtons.Button3, shift, prof);
            SetButton(StrategicButtons.Button4, shift, prof);
            SetButton(StrategicButtons.Button5, shift, prof);
            SetButton(StrategicButtons.Button6, shift, prof);
            //SetButton(StrategicButtons.Rec, shift, prof);
            RefreshLedStatus();
        }

        private void SetButton(StrategicButtons button, StrategicShiftState shift, StrategicProfileSelector prof)
        {
            if (conf.GetAssignedButtons(button, shift, prof).IsUnassigned())
                SetLedStatus(button, StrategicLedStatus.Off);
            else
                SetLedStatus(button, StrategicLedStatus.On);
        }

        public void ImmediateSetLedStatus(StrategicButtons button, StrategicLedStatus status)
        {
            LedStatus[(int)button] = status;
            SendFeatureReport();
        }

        public void SetLedStatus(StrategicButtons button, StrategicLedStatus status)
        {
            LedStatus[(int)button] = status;
        }

        public void RefreshLedStatus()
        {
            SendFeatureReport();
        }

        private void SendFeatureReport()
        {
            byte value = 0;
            for (int i = 0; i < 4; i++){
                value += (byte)(LedFirst[i] * (int)LedStatus[i]);
            }
            rep.set_ReportData(0, value);
            value = 0;
            for (int i = 4; i < 7; i++)
            {
                value += (byte)(LedSecond[i - 4] * (int)LedStatus[i]);
            }
            rep.set_ReportData(1, value);
            mssc.WriteReport(rep);
        }

        public void Dispose()
        {
            LedStatus[0] = StrategicLedStatus.Off;
            LedStatus[1] = StrategicLedStatus.Off;
            LedStatus[2] = StrategicLedStatus.Off;
            LedStatus[3] = StrategicLedStatus.Off;
            LedStatus[4] = StrategicLedStatus.Off;
            LedStatus[5] = StrategicLedStatus.Off;
            LedStatus[6] = StrategicLedStatus.Off;
            LedStatus[7] = StrategicLedStatus.Off;
            RefreshLedStatus();
        }
    }
}
